%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Start of pgf-umlcd.sty
%
% Some macros for UML Class Diagrams.
% Home page of project: http://pgf-umlcd.googlecode.com/
% Author: Xu Yuan <xu@informatik.hu-berlin.de>, Humboldt University, Berlin
% Style from: http://www.ibm.com/developerworks/cn/rational/r-uml/
%

\NeedsTeXFormat{LaTeX2e}[1999/12/01]
\ProvidesPackage{pgf-umlcd}[2011/10/01 v0.3dev Some LaTeX macros for
UML Class Diagrams.]

\RequirePackage{tikz}

\usetikzlibrary{arrows,shapes.multipart,backgrounds,fit}
\tikzstyle{help lines}+=[blue!50,very thin,dashed]

\newcommand{\umltextcolor}{black}
\newcommand{\umldrawcolor}{purple}
\newcommand{\umlfillcolor}{yellow!20}
\tikzstyle{umlcolor}=[color=\umldrawcolor,fill=\umlfillcolor,text=\umltextcolor]
\tikzstyle{umlcd style}=[umlcolor, >=angle 90]

\tikzstyle{package}=[matrix, column sep=1mm, row sep=1cm, node distance=2cm]
\tikzstyle{packagename}=[rectangle, minimum height=2em]

\tikzstyle{umlcd style implement line}=[color=\umldrawcolor, open triangle 45-,dashed]
\tikzstyle{objectline}=[color=\umldrawcolor, diamond->]
\tikzstyle{umlcd style inherit line}=[color=\umldrawcolor, open triangle 45-]
\tikzstyle{splitline}=[color=\umldrawcolor, dotted,font=\itshape]

\tikzstyle{umlcd style class}=[rectangle split, rectangle split parts=3, 
every text node part/.style={text centered},
draw, minimum height=2em, umlcolor, minimum width=2cm, text width=5cm,
minimum height=1cm, node distance=2cm]


\tikzstyle{umlcd style dashed line}=[color=\umldrawcolor, >=angle 90,dashed]

\tikzstyle{umlcd style school}=[]
\newif\ifschool\schoolfalse
\DeclareOption{school}{\tikzstyle{umlcd style school}=[rounded corners] \schooltrue}
\newif\ifsimplified\simplifiedfalse
\DeclareOption{simplified}{\simplifiedtrue}
\ProcessOptions\relax


% declare layers
\pgfdeclarelayer{background}
\pgfdeclarelayer{connectionlayers}
\pgfsetlayers{background,connectionlayers,main}

\newcounter{umlcdClassAttributesNum}
\newcounter{umlcdClassOperationsNum}
\newcounter{umlcdClassAbstractClassNum}
\newcounter{umlcdClassInterfaceNum}
\newcounter{umlcdClassSplitPartNum}

\def\umlcdPackageFit{}

\newenvironment{class}[3][]%
{
\begin{classAndInterfaceCommon}{#1}{#2}{#3}
}%
{\calcuateNumberOfParts{}
\node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos)
    {\textbf{\umlcdClassName}
\insertAttributesAndOperations{}
};

\end{classAndInterfaceCommon}
}

\newenvironment{interface}[3][]%
{
\begin{classAndInterfaceCommon}{#1}{#2}{#3}
}%
{\calcuateNumberOfParts{}
\node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos)
    {$<<$interface$>>$ \\ \textbf{\umlcdClassName}
\insertAttributesAndOperations{}
};

\end{classAndInterfaceCommon}
}

\newenvironment{abstractclass}[3][]%
{
\begin{classAndInterfaceCommon}{#1}{#2}{#3}
}%
{\calcuateNumberOfParts{}
\node[this umlcd style, anchor=north] (\umlcdClassName) at (\umlcdClassPos)
    {$<<$abstract$>>$ \\ \textbf{\umlcdClassName}
\insertAttributesAndOperations{}
};

\end{classAndInterfaceCommon}
}

% TODO: here the name of \umlcdClassName and \umlObjectName should be
% switched, it is only for reusing \classAndInterfaceCommon at the
% moment.
\newenvironment{object}[3][]%
{
\begin{classAndInterfaceCommon}{#1}{#2}{#3}
\def\@instanceOf{}
\def\@@instanceOf{}
}%
{
  % customized
  \ifsimplified
  \calcuateNumberOfParts{}
  \else
  \ifnum\c@umlcdClassOperationsNum>0
  \setcounter{umlcdClassSplitPartNum}{3}
  \protected@xdef\umlcdSplitPart{3}
  \else
  \setcounter{umlcdClassSplitPartNum}{2}
  \protected@xdef\umlcdSplitPart{2}
  \fi
  \fi

	\ifx\@instanceOf\@@instanceOf
		\def\umldObjectName{\umlcdClassName}
	\else
		\def\umldObjectName{\umlcdClassName : \@instanceOf}
	\fi

\node[this umlcd style, anchor=north, umlcd style school] (\umlcdClassName) at (\umlcdClassPos)
    { \ifschool
				\textbf{\umldObjectName}
			\else 
				\underline{\textbf{\umldObjectName}}
			\fi
			\insertAttributesAndOperations{}
};

\end{classAndInterfaceCommon}
}

\newcommand*{\insertAttributesAndOperations}
{
  \ifnum\c@umlcdClassSplitPartNum>1
  \nodepart{second}
  \fi
  \umlcdClassAttributes
  \ifnum\c@umlcdClassSplitPartNum>2
  \nodepart{third}
  \fi
  \umlcdClassOperations
}

\newcommand*{\calcuateNumberOfParts}
{
  % calcuate the number of parts
  \ifsimplified
  \setcounter{umlcdClassSplitPartNum}{1}
  \ifnum\c@umlcdClassAttributesNum>0
  \stepcounter{umlcdClassSplitPartNum}
  \fi
  \ifnum\c@umlcdClassOperationsNum>0
  \stepcounter{umlcdClassSplitPartNum}
  \fi
  \else
  \setcounter{umlcdClassSplitPartNum}{3}% three parts by default
  \fi

  \protected@xdef\umlcdSplitPart{3}
  \ifnum\c@umlcdClassSplitPartNum=1
  \protected@xdef\umlcdSplitPart{1}
  \fi
  \ifnum\c@umlcdClassSplitPartNum=2
  \protected@xdef\umlcdSplitPart{2}
  \fi
}

\newenvironment*{classAndInterfaceCommon}[3]
{
\def\umlcdClassName{#2}%
\def\umlcdClassPos{#3}
\def\umlcdClassAttributes{}%
\def\umlcdClassOperations{}%
\def\umlcdClassAbstractClass{}%
\def\umlcdClassInterface{}%
\setcounter{umlcdClassAttributesNum}{0}%
\setcounter{umlcdClassOperationsNum}{0}%
\setcounter{umlcdClassAbstractClassNum}{0}%
\setcounter{umlcdClassInterfaceNum}{0}%
\tikzstyle{this umlcd style}=[umlcd style class, rectangle split
  parts=\umlcdSplitPart, #1]
}%
{
%% connections
\begin{pgfonlayer}{connectionlayers}
\ifnum\c@umlcdClassAbstractClassNum>0
\foreach \c in \umlcdClassAbstractClass {
  \draw [umlcd style inherit line] (\c) -- (\umlcdClassName);
}
\fi

\ifnum\c@umlcdClassInterfaceNum>0
\foreach \c in \umlcdClassInterface {
  \draw [umlcd style implement line] (\c) -- (\umlcdClassName);
}
\fi
\end{pgfonlayer}

%% add to fit
\let\umlcdPackageFitOld\umlcdPackageFit
\protected@xdef\umlcdPackageFit{\umlcdPackageFitOld (\umlcdClassName)}
}

\newcommand{\attribute}[1]{%
\ifnum\c@umlcdClassAttributesNum=0
\protected@xdef\umlcdClassAttributes{#1}
\else
\let\umlcdClassAttributesOld\umlcdClassAttributes
\protected@xdef\umlcdClassAttributes{\umlcdClassAttributesOld \ \newline
    #1}
\fi
\stepcounter{umlcdClassAttributesNum}
}

\newcommand{\operation}[2][1]{%
\stepcounter{umlcdClassOperationsNum}

\def\virtualoperation{#2}
\ifnum0=#1
\def\virtualoperation{\textit{#2}}
\fi

\ifnum\c@umlcdClassOperationsNum=1
\protected@xdef\umlcdClassOperations{\virtualoperation}
\else
\let\umlcdClassOperationsOld\umlcdClassOperations
\protected@xdef\umlcdClassOperations{\umlcdClassOperationsOld \ \newline
    \virtualoperation}
\fi
}

\newcommand{\inherit}[1]
{
\stepcounter{umlcdClassAbstractClassNum}
\ifnum\c@umlcdClassAbstractClassNum=1
\protected@xdef\umlcdClassAbstractClass{#1}
\else
\let\umlcdClassAbstractClassOld\umlcdClassAbstractClass
\protected@xdef\umlcdClassAbstractClass{\umlcdClassAbstractClassOld,
  #1}
\fi
}

\newcommand{\implement}[1]
{
\stepcounter{umlcdClassInterfaceNum}
\ifnum\c@umlcdClassInterfaceNum=1
\protected@xdef\umlcdClassInterface{#1}
\else
\let\umlcdClassInterfaceOld\umlcdClassInterface
\protected@xdef\umlcdClassInterface{\umlcdClassInterfaceOld,
  #1}
\fi
}

\newcommand{\instanceOf}[1]{\def\@instanceOf{#1}}

%\newcommand{\association}[6]{
%\draw [umlcd style] (#1) -- (#4)
%node[near start, above]{#2}
%node[near start, below]{#3}
%node[near end, above]{#5}
%node[near end, below]{#6};
%}

% 耿楠修改(2020.02.08)
\newcommand{\association}[7][{}]{
\draw [umlcd style] (#2) -- (#5)
node[midway, above]{$\blacktriangleleft$~#1}
node[very near start, above]{#3}%xshift=-0.5cm, 
node[very near start, below]{#4}
node[very near end, below]{#6}
node[very near end, above]{#7};
}

\newcommand{\unidirectionalAssociation}[4]{
\draw [umlcd style, ->] (#1) -- (#4)
node[near end, above]{#2}
node[near end, below]{#3};
}

\newcommand{\aggregation}[4]
{
\draw[umlcd style, open diamond->] (#1) -- (#4)
node[near end, above]{#2}
node[near end, below]{#3};
}

\newcommand{\composition}[4]
{
\draw[umlcd style, fill=\umldrawcolor, diamond->] (#1) -- (#4)
node[near end, above]{#2}
node[near end, below]{#3};
}

\newenvironment{package}[1]{
\def\umlcdPackageFit{}
\def\umlcdPackageName{#1}
}{
  \begin{pgfonlayer}{background}
  \node[umlcd style, draw, inner sep=0.5cm, fit = \umlcdPackageFit] (\umlcdPackageName) {};
  \node[umlcd style, draw, outer ysep=-0.5, anchor=south west] (\umlcdPackageName caption) at
  (\umlcdPackageName.north west) {\umlcdPackageName};
  \end{pgfonlayer}
}

\newcommand{\switchUmlcdSchool}{
	\ifschool
		\tikzstyle{umlcd style school}=[]
		\schoolfalse
	\else
		\tikzstyle{umlcd style school}=[rounded corners]
		\schooltrue
	\fi
}

\pgfdeclareshape{umlcdnote}{
\inheritsavedanchors[from=rectangle] % this is nearly a rectangle
\inheritanchorborder[from=rectangle]
\inheritanchor[from=rectangle]{center}
\inheritanchor[from=rectangle]{north}
\inheritanchor[from=rectangle]{south}
\inheritanchor[from=rectangle]{west}
\inheritanchor[from=rectangle]{east}
% ... and possibly more
\backgroundpath{% this is new
% store lower right in xa/ya and upper right in xb/yb
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
% compute corner of flipped page
\pgf@xc=\pgf@xb \advance\pgf@xc by-10pt % this should be a parameter
\pgf@yc=\pgf@yb \advance\pgf@yc by-10pt
% construct main path
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
\pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
\pgfpathclose
% add little corner
\pgfpathmoveto{\pgfpoint{\pgf@xc}{\pgf@yb}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
\pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}}
\pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}}
}
}

\newcommand{\umlnote}[1][]{
	\node[umlcd style, anchor=north, draw, shape=umlcdnote, text width=4cm, #1]
}

%%% End of pgf-umlcd.sty
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
